module Explode.EditGameState;
private import Explode.Editor;
private import Explode.GameState;
private import Explode.GameTitleState;
private import Explode.GameoverState;
private import Explode.PauseMenuState;
private import Explode.Stage;
private import Explode.Player;
private import Explode.GameConfig;
private import Explode.ScoreBoard;
private import State.IState;
private import Input.KeyCode;
private import Input.GamePad;
private import Input.Mouse;
private import Input.InputRecorder;
private import Graphics.IGraphics;
private import Sound.Manager;
private import System.Console;
private import std.file;
private import std.string;
private import std.format;


/**
*	エディットゲームプレイ用
**/
public class EditGameState : GameState{
	public static const int CLEAR = 100;
	public static const int DEAD  = 200;
	protected int _returnValue = 0;
	public int returnValue(){return _returnValue;}

	protected IState _caller;
	protected EditorState _editorState;
	protected bool _returnFlag;
	protected PauseScrollState _scroller; 
	protected string _fileName;

	public this( EditorState e ,IGraphics g ) {
		super( g );
		_editorState = e;
	} //

	public IState action() {
		_frameCnt++;
		_stage.action();
			 if ( _zoom > 0 ) _stage.zoomIn();
		else if ( _zoom < 0 ) _stage.zoomOut();


		if ( _pauseFlag ) return _scroller.call( this );
		if ( _stage.mode == GameStage.MODE_DEAD ) {
			ISoundSprite s = SoundManager.getSprite();
			s.play( _stage.missSound ).release();
			return _dying.call( _editorState );
		} else 
		if ( _stage.mode == GameStage.MODE_CLEAR ) {
			ISoundSprite s = SoundManager.getSprite();
			s.play( _stage.goalSound ).release();
			saveReplay();
			return _stageClear.call( _editorState );
		}
		
		if ( _gamepad.getButton( 0 )  > 0 && _gamepad.getButton( 1 ) > 0 ) {
			_giveupCnt++;
			if ( _giveupCnt > 180 ) _returnFlag = true;
		} else
			_giveupCnt = 0;
		if ( _gamepad.getButton( 8 ) > 0 ) _returnFlag = true;
		
		if ( _returnFlag ) return _editorState.call( this );

		return this;
	} //

	public IState call( IState caller ){
		_caller = caller;
		initObject();
		
		_zoom   = 0;
		_key_dn = 0;
		_key_up = 0;
		_key_lt = 0;
		_key_rt = 0;
		_pauseFlag = false;
		_returnFlag = false;
		
		if ( !(caller is _scroller ) )
			SoundManager.background.play( _stage.gameBgm , -1 );

		return nextCall( caller );
	} //
	
	protected void initObject(){
		if ( _stage is null ) {
			_gamepad	   = new VirtualGamePad( 8 );
			_mouse		   = new BasicMouse();
			_param		   = new GameParam();
			_stage		   = new EditGameStage( _graphics , _param );
			_stage.gamepad = _gamepad;
			_stage.mouse   = _mouse;
			_scroller	   = new PauseScrollState( this , _param , _gamepad , _graphics );
			_stageClear	   = new StageClearState( _stage , _param , _gamepad );
			_dying		   = new DyingState( _stage , _param );
			setStageNumber( GameConfig.lastStage );
		}
	} //
	
	public bool loadStage( string src ) {
		_fileName = "";
		_param.bestTime = getBestTime( _fileName );
		return _stage.loadStage( src );
	} //
	
	public bool loadStageFromFile( string fileName ) {
		_fileName = fileName;
		_param.bestTime = getBestTime( _fileName );
		return _stage.loadStageFromFile( fileName );
	} //


	protected IState nextCall( IState caller ) {
		return this;
	} //

	protected bool saveReplay() {
		string code = _stage.replayCode;
		if ( code is null ) return false;
		if ( _fileName.length == 0 ) return false;
		string[] filetmp = split( _fileName , "/" );
		string dir = join( filetmp[0..length-1] , "/" ) ~"/";
		string saveDir = dir ~ "replay/";
		if ( !exists( saveDir ) ) return false;
		int frameCnt = _stage.frameCnt;

		string file = saveDir ~ filetmp[ filetmp.length - 1 ];
		Console.writeln("savefile=%s",file);
		if ( exists( file ) ) {
			string content = cast(string)read( file );
			string chk = split( content , "[body]" )[0];
			if ( chk.length > 1 ) {
				int frm	   = cast(int)atoi( split( chk , "," )[0] );
				Console.writeln("BEST TIME=%d CURRENT TIME=%d" , frm , frameCnt );
				if ( frm < frameCnt ) return false;
			}
			remove( file );
		}
		Console.writeln("replaycode:\n" ~ code);
		write( file , code );
		return true;
	} //

	protected int getBestTime( string fileName ) {
		if ( _fileName.length == 0 ) return -1;
		string[] filetmp = split( _fileName , "/" );
		string dir = join( filetmp[0..length-1] , "/" ) ~"/";
		string saveDir = dir ~ "replay/";
		string file = saveDir ~ filetmp[ filetmp.length - 1 ];

		if ( exists( file ) ) {
			string content = cast(string)read( file );
			string chk = split( content , "[body]" )[0];
			if ( chk.length > 1 ) {
				return cast(int)atoi( split( chk , "," )[0] );
			}
		}
		return -1;
	} //


	public bool onKeyDown( int keyCode ){
		switch ( keyCode ) {
			case KeyCode.UP:
				_key_up = -1;
				_gamepad.y = -1;
				break;
			case KeyCode.DOWN:
				_key_dn =  1;
				_gamepad.y =  1;
				break;
			case KeyCode.LEFT:
				_key_lt = -1;
				_gamepad.x = -1;
				break;
			case KeyCode.RIGHT:
				_key_rt =  1;
				_gamepad.x =  1;
				break;
			case KeyCode.Z:
				_gamepad.setButton( 0 , 1 );
				break;
			case KeyCode.X:
				_gamepad.setButton( 1 , 1 );
				break;
			case KeyCode.PAGEDOWN:
				_zoom = -1;
				break;
			case KeyCode.PAGEUP:
				_zoom =  1;
				break;
			case KeyCode.HOME:
				_zoom =  0;
				break;
			case KeyCode.DELETE:
			case KeyCode.ENTER:
				_returnFlag = true;
				break;
			case KeyCode.SPACE:
				_pauseFlag = true;
				break;
			default:
				break;
		}
		return true;
	} //

} //

public class EditGameStage : GameStage {
	public this( IGraphics g , GameParam p ) {
		super( g , p );
	} //
	protected void initObject( IGraphics g , GameParam p ) {
		super.initObject( g , p);
		_scoreBoard = new EditScoreBoard( this , p );
	} //
} //


public class EditScoreBoard : ScoreBoard {
	public this( GameStage stage , GameParam param ) {
		super( stage , param );
	} //

	public bool draw( IGraphics g ) {
		float clipX  = g.viewrect.x  , clipY  = g.viewrect.y , 
			  clipX2 = g.viewrect.x2 , clipY2 = g.viewrect.y2;
		const int W=16;
		const int H=16;

		Player p  = _stage.player;
		_frameCnt = _stage.frameCnt;
		_goldCnt  = _stage.goldCnt;
		_lifeCnt  = _param.life;
		_stageNum = _param.stageNum;
		_score	  = p.score + _param.score;
		g.setViewport( 0 , 0 , W * 40 , H * 30 ); 
		int bm  = g.blendMode;
		{
			Color c;
			c.color = 0xaa000033;
			g.drawFilledRect( 0 ,  H * 29 -4 , W * 40 , 32 , c );

			g.blendMode = g.ALPHA_ADD;
			c.color = 0xccffff00;
			
			string top	  = format( "LIFE %d  STAGE %03d  MODE %s" 
									, _lifeCnt , _stageNum , _stage.cpu) ;
			string top2	  = format( "     %d        %03d       %s" 
									, _lifeCnt , _stageNum , _stage.cpu) ;
			string bottom  = format( "GOLD %03d   SCORE %06d   TIME %06d" , _goldCnt , _score , _frameCnt ) ;
			string bottom2 = format( "     %03d         %06d        %06d" , _goldCnt , _score , _frameCnt ) ;
			int tx = cast(int)(W * 40 - top.length * W   ) / 2;
			int bx = cast(int)(W * 40 - bottom.length *W ) / 2;

			g.drawText( bottom , bx  , H * 29 -2 , c , W , H );

			g.blendMode = bm;

			c.color = ( _goldCnt > 0 ) ? 0xccffffff : 0xcc00ffff; 
			g.drawText( bottom2, bx  , H * 29 -2 , c , W , H );
			if ( _param.bestTime > 0 ) {
				string btime = format( "                     BEST TIME %06d" , _param.bestTime ) ;
				Color col = Color.create(( _frameCnt < _param.bestTime ) ? 0xffffff00 : 0xff888888 ) ;
				g.drawText( btime , bx  , 0 , col , W , H );
			}
		}
		g.setViewport( clipX , clipY , clipX2 , clipY2);
		return true;
	} //

} //

